/**
  * Author: Mei
  * Date: 2020-12-30 19:13
  * Description: 在运行期通过索引来取值
  * int i = 1;
    cout << get<i>(tp) << endl; //在编译期很容易根据索引来获取对应位置的元素，
        然而我们不能在运行期通过变量来获取tuple中的元素值
  *
  */
#include "../head.h"

template<size_t k, typename Tuple>
typename enable_if<(k == tuple_size<Tuple>::value), void>::type
GetArgByIndex(size_t index, Tuple &tp) {
    cout << "aaa: " << tuple_size<Tuple>::value << ", k=" << k << endl;
    throw invalid_argument("arg index out of range");
};

/**
 * //通过递归的方式自增编译器常量k 将k与运行期变量index做比较，当二者相等时，调用编译器常量k
 * 来获取tuple中的第k个元素值
 *
 */
template<size_t k = 0, typename Tuple>
typename enable_if<(k < tuple_size<Tuple>::value), void>::type
GetArgByIndex(size_t index, Tuple &tp) {
    cout << "----- k=" << k << endl;
    if (k == index) {
        cout << get<k>(tp) << endl;
    } else {
        GetArgByIndex<k + 1>(index, tp);
    }
};

//另外一种方法
template<typename Arg>
void
GetArgByIndex1(int index, tuple<Arg> &tp) { //当tuple中只有一种类型的时候才会执行
    cout << "+++" << endl;
    cout << get<0>(tp) << endl;
};

template<typename Arg, typename ... Args>
void
GetArgByIndex1(int index, tuple<Arg, Args...> &tp) {
    if(index < 0 || index >= tuple_size<tuple<Arg, Args...>>::value) {
        throw invalid_argument("arg index out of range");
    }
    if(index > 0) {
        GetArgByIndex1(index - 1, (tuple<Args...>&)tp);
    } else {
        cout << "----" << endl;
        cout << get<0>(tp) << endl;
    }
};

void TestTuple() {
    using Tuple = tuple<int, short, double, char, int, bitset<8>>;
    Tuple tp = make_tuple(1, 2, 3, 'a', 10, 29);
    const size_t length = tuple_size<Tuple>::value;

    for (size_t i = 0; i < length; ++i) {
        GetArgByIndex1(i, tp);
    }
    //GetArgByIndex1(3, tp);
}


int main() {
    tuple<int, short, double, char, int, bitset<8>> tp = make_tuple(1, 2, 3, 'a', 10, 29);
    //cout << get<1>(tp) << endl;

    TestTuple();

    return 0;
}